package test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import javax.swing.JFrame;

import AStar.AStarPathNotFoundException;

import nav.CoordinateImpl;
import nav.Coordinate;
import nav.FileManager;
import nav.Navigation;
import nav.NavigationImpl;
import nav.Route;

public class Main {
	
    static JFrame F=new JFrame();
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Navigation nav = new NavigationImpl();

		double left = -9.8;
		double right = -10;
		double top = 49.81;
		double bottom = 49.78;
				
		nav.getFromDatabase(left,right,top,bottom);

			
		nav.getFromFiles();
		String routeFileName = "route.txt";
		//List<Coordinate> pois = FileManager.getPoisFromFile(routeFileName);
		List<Coordinate> pois = getRandomPois(20,left,right,top,bottom);
		Route route = null;
		try {
			route = nav.executeNavigation(pois.toArray(new Coordinate[]{}));
		} catch (AStarPathNotFoundException e) {
			System.out.println("...No Path Found.");
		}
		route.setFileName(routeFileName);
		writeFile(route);
	
		Runtime rt = Runtime.getRuntime();
		try {
			rt.exec(new String[]{"dorenda_paint.bat",route.getFileName()});
		} catch (IOException e) {
			System.out.println("Can't start Dorenda.");
		}
	}
	
	private static Options parseArguments(String[] args) {
		Options options = new Options();

		Queue<String> messageQueue = new LinkedList<String>();
		for(String string : args){
			messageQueue.add(string);
		}
		while(!messageQueue.isEmpty()){
			String message = messageQueue.poll();
			if(messageEquals(message,Options.Help)){
				printUserHelp();
				options.setHelpRequired(true);
				return options;
			}
			if(messageEquals(message,Options.Databank)){
				if(messageQueue.size() < 4){
					printUserHelp();
					options.setHelpRequired(true);
					return options;
				}
				String leftString = messageQueue.poll();
				double left = Double.parseDouble(leftString);
				String rightString = messageQueue.poll();
				double right = Double.parseDouble(rightString);
				String topString = messageQueue.poll();
				double top = Double.parseDouble(topString);
				String bottomString = messageQueue.poll();
				double bottom = Double.parseDouble(bottomString);
				options.setLeft(left);
				options.setRight(right);
				options.setTop(top);
				options.setBottom(bottom);
				options.setDatabankFlag(true);
			}
			if(messageEquals(message,Options.Navigation)){
				String fileName = messageQueue.poll();
				options.addRouteFileName(fileName);
			}
			if(messageEquals(message,Options.Dorenda)){
				options.setDorendaFlag(true);
			}
		}
		return options;
	}

	private static void printUserHelp() {
		System.out.println("--------HELP--------");
		System.out.println("Program Commands:");
		System.out.println("");
		System.out.println("For Databank use one of the following Commands: ");
		printCommands(Options.Databank);
		System.out.println("followed by the Ranges <left> <right> <top> <bottom>");
		System.out.println("");
		System.out.println("For Navigation use one of the following Commands: ");
		printCommands(Options.Navigation);
		System.out.println("");
		System.out.println("For painting with Dorenda use one of the following commands: ");
		printCommands(Options.Dorenda);
		System.out.println("");
		System.out.println("For Help use one of the following commands: ");
		printCommands(Options.Help);
		System.out.println("");
	}

	private static void printCommands(String[] commands){
		for(String string : commands){
			System.out.print(string + " ");
		}
		System.out.print("\r\n");
	}
	
	private static boolean messageEquals(String message, String[] Messages) {
		for(String string : Messages){
			if(string.equals(message)){
				return true;
			}
		}
		return false;
	}

	private static void writeFile(Route route){
		try {
			BufferedWriter writer = new BufferedWriter(new FileWriter(route.getFileName()));
			writer.write("LINE mode=1 col=255,0,0,150 startflag=\"START Tour "+ route.getLength() +" m\"\r\n");
			for(Coordinate coordinate : route.getTour()){
				writer.write(coordinate.toString() + "\r\n");
			}
			for(Coordinate poi : route.getPOIS()){
				writer.write("POSITIONS rad=10 col=0,255,0,255 \r\n");
				writer.write(poi.toString()+"\r\n");
			}
			Coordinate[] orderedCoordinates = route.getOrderedPOICoordinates();
			for(int i=1;i<orderedCoordinates.length-1;i++){
				writer.write("POSITIONS rad=10 col=255,255,255,0 text=\""+i+"\" \r\n");
				writer.write(orderedCoordinates[i].toString()+"\r\n");	
			}
//			for(Crossing crossing : route.getCrossings()){
//				writer.write("POSITIONS rad=10 col=0,0,255,255 text=\""+crossing.getID()+"\" \r\n");
//				writer.write(crossing.getCoordinate().toString() + "\r\n");
//			}
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static List<Coordinate> getRandomPois(int amount,double left, double right, double top, double bottom) {
		List<Coordinate> pois = new ArrayList<Coordinate>();
		for(int i = 0;i<amount;i++){
			double x = getRandDoubleInRange(right,left);
			double y = getRandDoubleInRange(bottom,top);
			pois.add(new CoordinateImpl(x,y));
		}		
		return pois;
	}
	
	private static double getRandDoubleInRange(double min, double max) {
		double value = Math.random() * (max- min) + min;
		return value;
	}
	
	private static List<Coordinate> getPOIs() {
		List <Coordinate> pois = new ArrayList<Coordinate>();
		
		pois.add(getCoordinate(-10.968938,49.603313));
		pois.add(getCoordinate(-10.969227,49.603900));
		
//		pois.add(getCoordinate(-011.08192167,49.44643333));
//		pois.add(getCoordinate(-011.07457667,49.45309667));
//		pois.add(getCoordinate(-011.07822167,49.45407000));
//		pois.add(getCoordinate(-011.07872833,49.45099333));
//		pois.add(getCoordinate(-011.07800167,49.45278833));
//		pois.add(getCoordinate(-011.07534833,49.44784167));
//		pois.add(getCoordinate(-011.07682000,49.45281167));
//		pois.add(getCoordinate(-011.08782000,49.45281167));
//		pois.add(getCoordinate(-011.07296667,49.45303000));
//		pois.add(getCoordinate(-011.07482667,49.45849000));
//		pois.add(getCoordinate(-011.07454500,49.455767333));
//		pois.add(getCoordinate(-011.07088167,49.45416000));
//		pois.add(getCoordinate(-011.07152333,49.45617667));
//		pois.add(getCoordinate(-011.07395000,49.45712667));
//		pois.add(getCoordinate(-011.07654500,49.45767333));
//		pois.add(getCoordinate(-011.08166233,49.457541667));
//		pois.add(getCoordinate(-011.07285000,49.457281267));
//		pois.add(getCoordinate(-011.07622450,49.458577333));
		return pois;
	}
	
	private static Coordinate getCoordinate(double Long, double Lat) {
		return new CoordinateImpl(Long,Lat);
	}
	
	private static class Options{

		private boolean dorendaFlag;
		private boolean databankFlag;
		private boolean helpRequired;
		private List<String> routeFileNames;
		private double bottom;
		private double top;
		private double right;
		private double left;
		
		public Options(){
			dorendaFlag = false;
			databankFlag = false;
			helpRequired = false;
			routeFileNames = new ArrayList<String>();
			bottom = 0;
			top = 0;
			right = 0;
			left = 0;
		}
		
		public void setDorendaFlag(boolean flag) {
			dorendaFlag = flag;
		}

		public void addRouteFileName(String fullFileName) {
			routeFileNames.add(fullFileName);
		}

		public void setBottom(double bottom) {
			this.bottom = bottom;
		}

		public void setTop(double top) {
			this.top = top;
		}

		public void setRight(double right) {
			this.right = right;
		}

		public void setLeft(double left) {
			this.left = left;
		}

		public void setDatabankFlag(boolean flag) {
			this.databankFlag = flag;
		}

		public void setHelpRequired(boolean helpRequired) {
			this.helpRequired = helpRequired;
		}

		public boolean helpRequired() {
			return helpRequired;
		}

		public boolean getDataBaseFlag() {
			return databankFlag;
		}

		public List<String> getRouteFileNames() {
			return routeFileNames;
		}

		public boolean getDorendaFlag() {
			return dorendaFlag;
		}

		public double getBottom() {
			return bottom;
		}

		public double getLeft() { 
			return left;
		}

		public double getRight() {
			return right;
		}

		public double getTop() {
			return top;
		}
		
		public final static String[] Help = new String[]{"help","-help","--help","-h","--h"};
		public final static String[] Databank = new String[]{"databank", "db", "-db", "-databank"};
		public final static String[] Navigation = new String[]{"execNavigation", "Navi", "navi", "executeNavigation"};
		public final static String[] Dorenda = new String[]{"paintDorenda", "paint_Dorenda", "dorenda"};
	}
}
